package com.eleadmin.damon.service.impl;

import com.eleadmin.damon.utils.utils.GuavaUitl;
import com.eleadmin.common.core.web.JsonResult;
import com.eleadmin.damon.biz.DataBaseBiz;
import com.eleadmin.damon.entity.DataBaseTable;
import com.eleadmin.damon.result.ColumnsResult;
import com.eleadmin.damon.result.TableResult;
import com.eleadmin.damon.service.DataBaseService;
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.FileResourceLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;

/**
 * 报关运费服务实现类
 *
 * @author : Doman
 * @version ：1.0
 * @date : 2023-05-06 10:59:18
 */
@Service
public class DataBaseServiceImpl implements DataBaseService {

    @Autowired
    private DataBaseBiz dataBaseBiz;
    private static final String DEF_ENCODING = "utf-8";

    @Override
    public JsonResult generate(DataBaseTable dataBaseTable) throws Exception {
        String cmdDir[] = { "explorer.exe", dataBaseTable.getOpenSource() };
        Runtime.getRuntime().exec(cmdDir);
        TableResult tableResult = dataBaseBiz.tableName(dataBaseTable);
        List<ColumnsResult> columns = dataBaseBiz.columns(dataBaseTable);

        List<String> columnNameList;List<String> columnNameNoCAMELList;List<String> dataTypeList;List<String> columnCommentList;
        columnNameList = new ArrayList<String>();columnNameNoCAMELList = new ArrayList<String>();dataTypeList = new ArrayList<String>();columnCommentList = new ArrayList<String>();
        for (int i=0; i < columns.size(); i ++) {
            ColumnsResult columnsResult = columns.get(i);
            columnNameList.add(GuavaUitl.LOWER_CAMEL(columnsResult.getColumnName()));
            columnNameNoCAMELList.add(columnsResult.getColumnName());
            dataTypeList.add(columnsResult.getDataType());
            columnCommentList.add(columnsResult.getColumnComment());
        }
        String root = System.getProperty("user.dir")
                + File.separator+"src"+ File.separator+"main"
                + File.separator+"java"+ File.separator+"com"
                + File.separator+"eleadmin" + File.separator+"damon"
                + File.separator+"template";
        FileResourceLoader resourceLoader = new FileResourceLoader(root,"utf-8");
        Configuration cfg = Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);

        createFile(dataBaseTable, tableResult, gt,columnNameList,columnNameNoCAMELList,dataTypeList,
                columnCommentList);
        return JsonResult.ok("修改成功").setData(tableResult);
    }


    public void createFile(DataBaseTable dataBaseTable, TableResult tableResult,
                           GroupTemplate gt, List<String> columnNameList, List<String> columnNameNoCAMELList,
                           List<String> dataTypeList, List<String> columnCommentList) throws Exception {
        String tableNameJavaEntityDx = dx(dataBaseTable.getTableNameJavaEntity());
        String tableNameJavaEntity = dataBaseTable.getTableNameJavaEntity();
        String packages = dataBaseTable.getPackages();
        String writesource = dataBaseTable.getSource();
        String writepackage = dataBaseTable.getSourceJava();
        String writepage = dataBaseTable.getSourceHtml();
        makedir(dataBaseTable);

        Template t = gt.getTemplate("/Controller.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + writepackage + packages + "/controller/" + tableNameJavaEntityDx + "Controller.java");

        t = gt.getTemplate("/Service.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + writepackage + packages + "/service/" + tableNameJavaEntityDx + "Service.java");

        t = gt.getTemplate("/ServiceImpl.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + writepackage + packages + "/service/impl/" + tableNameJavaEntityDx + "ServiceImpl.java");

        t = gt.getTemplate("/Biz.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + writepackage + packages + "/biz/" + tableNameJavaEntityDx + "Biz.java");

        t = gt.getTemplate("/BizImpl.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + writepackage + packages + "/biz/impl/" + tableNameJavaEntityDx + "BizImpl.java");

/*
		t = gt.getTemplate("/Mapper.txt");
		initData(dataBaseTable, t,columnNameList,columnNameNoCAMELList,dataTypeList,columnCommentList,tableNameJavaEntity,tableName,tableComment);
		writeFile(t, writesource+writepackage+packages+"/mapper/" + tableNameJavaEntityDx+"Mapper.java");

		t = gt.getTemplate("/MapperXml.txt");
		initData(dataBaseTable, t,columnNameList,columnNameNoCAMELList,dataTypeList,columnCommentList,tableNameJavaEntity,tableName,tableComment);
		writeFile(t, writesource+writepackage+packages+"/mapper/xml/" + tableNameJavaEntityDx+"Mapper.xml");
*/
        t = gt.getTemplate("/Entity.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + writepackage + packages + "/entity/" + tableNameJavaEntityDx + ".java");

//		t = gt.getTemplate("/list.txt");
//		initData(dataBaseTable, t,columnNameList,columnNameNoCAMELList,dataTypeList,columnCommentList,tableNameJavaEntity,tableName,tableComment);
//		writeFile(t, writesource+writepage+packages+"/" + tableNameJavaEntityDx+".html");

        t = gt.getTemplate("/Sql.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + "sql.txt");

        t = gt.getTemplate("/indexJs.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + "src/api/" + packages + "/" + tableNameJavaEntity + "/" + "index" + ".js");

        t = gt.getTemplate("/indexHtml.txt");
        initData(dataBaseTable, t, columnNameList, columnNameNoCAMELList, dataTypeList, columnCommentList, tableNameJavaEntity, tableResult.getTableName(), tableResult.getTableComment());
        writeFile(t, writesource + "src/views/" + packages + "/" + tableNameJavaEntity + "/" + "index" + ".vue");
    }

    public void writeFile(Template t, String fileName) throws Exception {
        String str = t.render();
//		System.out.println(str);
        BufferedWriter bufferedWriter = null;
        bufferedWriter = new BufferedWriter(new FileWriter(fileName));
        bufferedWriter.write(str);
        if (bufferedWriter != null) {
            bufferedWriter.flush();
            bufferedWriter.close();
        }
    }

    /**
     * 初始化VelocityContext
     *
     * @author wanghjbuf
     */
    public void initData(DataBaseTable dataBaseTable, Template t, List<String> columnNameList,
                         List<String> columnNameNoCAMELList, List<String> dataTypeList,
                         List<String> columnCommentList, String tableNameJavaEntity,
                         String tableName, String tableComment) throws Exception {
        List<String> dataTypeListJava = new ArrayList<String>();
        List<String> dataTypeListJavaReal = new ArrayList<String>();
        List<String> columnNameDxList = new ArrayList<String>();
        String hasDate = "no";
        for (int i = 0; i < dataTypeList.size(); i++) {
            String dataType = dataTypeList.get(i);
            String columnName = columnNameList.get(i);
            if (!dataType.equals("")) {
                if (dataType.equals("varchar")) {
                    dataTypeListJava.add("String");
                    dataTypeListJavaReal.add("String");
                } else if (dataType.equals("int") || dataType.equals("smallint")) {
                    dataTypeListJava.add("Integer");
                    dataTypeListJavaReal.add("Integer");
                } else if (dataType.equals("datetime") || dataType.equals("date")) {
                    dataTypeListJava.add("String");
                    dataTypeListJavaReal.add("Date");
                    if (!columnName.equals("create_time") && !columnName.equals("update_time")) {
                        hasDate = "yes";
                    }
                } else {
                    dataTypeListJava.add("String");
                    dataTypeListJavaReal.add("String");
                }
            } else {
                dataTypeListJava.add("String");
                dataTypeListJavaReal.add("String");
            }
        }
        for (int i = 0; i < columnNameList.size(); i++) {
            String columnNameDx = columnNameList.get(i);
            columnNameDxList.add(dx(columnNameDx));
        }

        String packages = dataBaseTable.getPackages();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("packages", packages);
        map.put("hasDate", hasDate);
        map.put("now", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        map.put("tableName", tableName);
        map.put("tableNameJavaEntity", tableNameJavaEntity);
        map.put("tableNameJavaEntityDx", dx(tableNameJavaEntity));
        map.put("tableComment", tableComment);
        map.put("sqlTable", tableNameJavaEntity.substring(0, 1));
        map.put("columnNameNoCAMELList", columnNameNoCAMELList);
        map.put("columnNameList", columnNameList);
        map.put("columnNameDxList", columnNameDxList);
        map.put("dataTypeListJava", dataTypeListJava);
        map.put("dataTypeListJavaReal", dataTypeListJavaReal);
        map.put("columnCommentList", columnCommentList);
        map.put("permissionAdd", "<% if(so.hasPermission(\"" + packages + ":" + tableNameJavaEntity + ":save\")){ %>");
        map.put("permissionUpdate", "<% if(so.hasPermission(\"" + packages + ":" + tableNameJavaEntity + ":update\")){ %>");
        map.put("permissionDelete", "<% if(so.hasPermission(\"" + packages + ":" + tableNameJavaEntity + ":remove\")){ %>");
        map.put("permissionEnd", "<% } %>");
//		map.put("listPageIncludecss", "<% include(\"../layout/css.html\"){} %>");
//		map.put("listPageIncludejs", "<:include file=\"../common/js.html\"/>");
        t.binding("d", map);
    }

    public String dx(String nameString) {
        String str1 = nameString.substring(0, 1).toUpperCase().concat(nameString.substring(1));
        return str1;
    }

    public void makedir(DataBaseTable dataBaseTable) {
        String packages = dataBaseTable.getPackages();
        String writeSource = dataBaseTable.getSource();
        String tableNameJavaEntity = dataBaseTable.getTableNameJavaEntity();

        delAllFile(writeSource);

        File file = new File(writeSource + "main/java/com/eleadmin/" + packages + "/controller");
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(writeSource + "main/java/com/eleadmin/" + packages + "/entity");
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(writeSource + "main/java/com/eleadmin/" + packages + "/service/impl");
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(writeSource + "main/java/com/eleadmin/" + packages + "/biz/impl");
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(writeSource + "main/java/com/eleadmin/" + packages + "/mapper/xml");
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(writeSource + "main/resources/templates/" + packages);
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(writeSource + "src/api/" + packages + "/" + tableNameJavaEntity);
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(writeSource + "src/views/" + packages + "/" + tableNameJavaEntity);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    // 删除指定文件夹下所有文件
    // param path 文件夹完整绝对路径
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);// 再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }

    // 删除文件夹
    // param folderPath 文件夹完整绝对路径
    public static void delFolder(String folderPath) {
        try {
            delAllFile(folderPath); // 删除完里面所有内容
            String filePath = folderPath;
            filePath = filePath.toString();
            File myFilePath = new File(filePath);
            myFilePath.delete(); // 删除空文件夹
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取Velocity写入流
     *
     * @author wanghjbuf
     */
    public BufferedWriter getWriterStream(String name) throws Exception {
        try {
            FileOutputStream fos = new FileOutputStream(name);
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, DEF_ENCODING));
            return writer;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
